﻿using DeHeng_Mes.Dao;
using DeHeng_Mes.Dao.PlcDao;
using DeHeng_Mes.Mapper;
using DeHeng_Mes.Model;
using DeHeng_Mes.Model.Singleton;
using DeHeng_Mes.Model.Table;
using DeHeng_Mes.Utils;
using Google.Protobuf.Collections;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MappingTable = DeHeng_Mes.Utils.MappingTable;

namespace DeHeng_Mes.Thread
{
    public class ErrorGather
    {
        PlcDao plcDao = new PlcDao();

        List<ErrorCache> lists = ErrorList.Lists;

        DeviceDao deviceDao = new DeviceDao();

        public async Task PlcErrorGather()
        {
            Tools.ProduceLogText("故障采集线程初始化成功！");

            while (true)
            {
                await Task.Delay(100);

                List<Model.PlcModel.PlcConfigModel> plcContainer = PlcConnectionManager.plcContainer;


                if (plcContainer == null)
                    continue;
                if (!(plcContainer.Count > 0))
                    continue;

                foreach (var plcConfig in plcContainer)
                {
                    try
                    {
                        // 未连接，跳过
                        if (!plcConfig.isConnected)
                            continue;

                        string plcName = plcConfig.name;

                        // 获取Plc数据实例与实例类型
                        Dictionary<object, Type> obj = MappingTable.PlcMapping(plcConfig.plc, plcName);

                        // 获取故障数据
                        Dictionary<string, object> errorData = plcDao.GetFieldValues(obj, "ErrorStatus");

                        // 解析故障
                        foreach (var errorType in errorData)
                        {
                            Dictionary<int, DeviceFault> deviceFaults = new Dictionary<int, DeviceFault>();

                            string typeName = ErrorMappingTable.GetTypeName(errorType.Key);

                            if (string.IsNullOrEmpty(typeName))
                                continue;

                            if (errorType.Key.Contains("Independent") && (bool)errorType.Value)
                            {
                                // 判断故障是否已存在缓存中，存在则跳过
                                if (IsExist(true, typeName))
                                    continue;

                                // 截取索引
                                string index = errorType.Key.Replace("Independent", "");

                                deviceFaults.Add(int.Parse(index + "8000"), IndependentDataAssembly(new DeviceFault(), typeName, plcConfig));
                            }
                            else
                            {
                                if (errorType.Key.Equals("Robot"))
                                    continue;

                                if (errorData[errorType.Key] is bool[] boolArray)
                                {
                                    for (int i = 0; i < boolArray.Length; i++)
                                    {
                                        bool currentValue = boolArray[i];

                                        // 如果为真，则触发报警
                                        if (currentValue)
                                        {
                                            // 获取详细报错信息
                                            string message = ErrorMappingTable.GetMessage(plcName, errorType.Key, i);

                                            if (string.IsNullOrEmpty(message))
                                                continue;

                                            // 判断故障是否已存在缓存中，存在则跳过
                                            if (IsExist(false, message))
                                                continue;

                                            // 组装数据
                                            deviceFaults.Add(i, DataAssembly(new DeviceFault(), typeName, message, plcConfig));
                                        }
                                    }
                                }
                            }

                            // 判断DeviceFault是否存在故障数据，如果已经实例化进行下一步操作
                            if (deviceFaults.Count > 0)
                            {
                                foreach (var deviceFault in deviceFaults)
                                {
                                    // 存入数据库
                                    deviceDao.ErrorDataInit(deviceFault.Value);

                                    // 初始化故障缓存类
                                    ErrorCache errorCache = new ErrorCache()
                                    {
                                        deviceFault = deviceFault.Value,
                                        Index = deviceFault.Key,
                                        PlcName = plcName,
                                        PlcIn = plcConfig.plc,
                                    };

                                    // 存入缓存列表
                                    lists.Add(errorCache);
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Tools.ProduceLogTextError($"故障采集失败，原因是：{e.Message}");
                    }
                }

                await Task.Delay(1000);
            }
        }

        /// <summary>
        /// 采集故障结束状态与时间
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task PlcErrorGatherEndTime()
        {
            Tools.ProduceLogText("故障结束状态检测线程启动成功！");
            while (true)
            {
                try
                {
                    await Task.Delay(100);

                    // 初始化移除项
                    List<ErrorCache> errorCaches = new List<ErrorCache>();

                    if (lists != null && lists.Count > 0)
                    {
                        // 存在故障，检测故障状态
                        foreach (var errorMessage in lists)
                        {
                            // 取出故障索引
                            string index = errorMessage.Index.ToString();

                            // 取出plcName
                            string plcName = errorMessage.PlcName;

                            // 取出Plc实例
                            S7.Net.Plc plc = errorMessage.PlcIn;

                            // 取出故障数据
                            DeviceFault deviceFault = errorMessage.deviceFault;

                            // 获取Plc数据实例与实例类型
                            Dictionary<object, Type> obj = MappingTable.PlcMapping(plc, plcName);

                            // 判断索引
                            if (index.Length > 3)
                            {
                                // 提取数据
                                string indexResult = index.Replace("8000", "");

                                // 获取故障数据
                                bool status = plcDao.GetBoolFieldValue(obj, "ErrorStatus", $"Independent{int.Parse(indexResult)}");

                                if (!status)
                                {
                                    // 故障结束，处理数据
                                    deviceDao.UpDateEndErrorTime(deviceFault);

                                    errorCaches.Add(errorMessage);
                                }
                            }
                            else
                            {
                                // 处理数组数据
                                Dictionary<string, object> dictionary = plcDao.GetFieldValues(obj, "ErrorStatus");

                                foreach (var errorType in dictionary)
                                {
                                    string key = ErrorMappingTable.GetTypeKey(deviceFault.FaultType);

                                    if (!string.IsNullOrEmpty(key))

                                        if (errorType.Key.Equals(key))
                                        {
                                            if (dictionary[errorType.Key] is bool[] boolArray)
                                            {
                                                bool isOk = boolArray[int.Parse(index)];

                                                if (!isOk)
                                                {
                                                    // 故障结束，处理数据
                                                    deviceDao.UpDateEndErrorTime(deviceFault);

                                                    errorCaches.Add(errorMessage);
                                                }
                                            }
                                        }
                                }
                            }
                        }
                    }

                    if (errorCaches != null && errorCaches.Count > 0)
                    {
                        foreach (var errorCache in errorCaches)
                        {
                            lists.Remove(errorCache);

                            Tools.ProduceLogText($"成功移除了一个故障，故障信息为{errorCache.deviceFault.FaultMessage}剩余{lists.Count}个故障未处理");
                        }
                    }
                }
                catch (Exception e)
                {
                    Tools.ProduceLogTextError($"处理故障结束异常，原因是{e.Message}");
                }
                await Task.Delay(500);
            }
        }

        /// <summary>
        /// 判断报警是否存在于缓存数据中
        /// </summary>
        /// <param name="isType"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private bool IsExist(bool isType, string message)
        {

            if (lists != null && lists.Count > 0)
            {
                foreach (var errorMessage in lists)
                {
                    if (isType)
                    {
                        if (errorMessage.deviceFault.FaultType.Equals(message))
                        {
                            return true;
                        }
                    }
                    else
                    {
                        if (errorMessage.deviceFault.FaultMessage.Equals(message))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 组装报警数据，有详细信息
        /// </summary>
        /// <param name="deviceFault"></param>
        /// <param name="typeName"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private DeviceFault DataAssembly(DeviceFault deviceFault, string typeName, string message, Model.PlcModel.PlcConfigModel plcConfig)
        {
            deviceFault.PlcName = plcConfig.nick;

            deviceFault.FaultType = typeName;

            deviceFault.FaultMessage = message;

            deviceFault.StopStartTime = DateTime.Now;

            return deviceFault;
        }

        /// <summary>
        /// 组装报警数据，无详细信息
        /// </summary>
        /// <param name="deviceFault"></param>
        /// <param name="typeName"></param>
        /// <returns></returns>
        private DeviceFault IndependentDataAssembly(DeviceFault deviceFault, string typeName, Model.PlcModel.PlcConfigModel plcConfig)
        {
            deviceFault.PlcName = plcConfig.name;

            deviceFault.FaultType = typeName;

            deviceFault.FaultMessage = "无具体信息";

            deviceFault.StopStartTime = DateTime.Now;

            return deviceFault;
        }
    }
}
